package com.thor.palmmall.util.pay;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import com.google.common.collect.Maps;
import com.thoughtworks.xstream.annotations.XStreamAlias;

/**
 * @author Niu Li
 * @date 2016/10/29
 */
public class SignUtil {

  /**
   * 连接Map键值对
   *
   * @param map
   *          Map
   * @param prefix
   *          前缀
   * @param suffix
   *          后缀
   * @param separator
   *          连接符
   * @param ignoreEmptyValue
   *          忽略空值
   * @param ignoreKeys
   *          忽略Key
   * @return 字符串
   */
  public static String joinKeyValue(Map<String, Object> map, String prefix, String suffix,
      String separator, boolean ignoreEmptyValue, String... ignoreKeys) {
    List<String> list = new ArrayList<String>();
    if (map != null) {
      for (Map.Entry<String, Object> entry : map.entrySet()) {
        String key = entry.getKey();
        String value = String.valueOf(entry.getValue());
        if (StringUtils.isNotEmpty(key) && !ArrayUtils.contains(ignoreKeys, key)
            && (!ignoreEmptyValue || StringUtils.isNotEmpty(value))) {
          list.add(key + "=" + (value != null ? value : ""));
        }
      }
    }
    return (prefix != null ? prefix : "") + StringUtils.join(list, separator)
        + (suffix != null ? suffix : "");
  }

  /**
   * 把request请求参数转换为Map<String,String>
   * 
   * @param request
   *          该请求
   * @return Map<String,String>格式的参数
   */
  public static Map<String, String> request2Map(HttpServletRequest request) {
    Enumeration<String> names = request.getParameterNames();
    Map<String, String> resData = new HashMap<String, String>();
    while (names.hasMoreElements()) {
      String name = names.nextElement();
      resData.put(name, request.getParameter(name));
    }
    return resData;
  }

  /**
   * Bean转map
   * 
   * @param bean
   *          要转的bean
   * @return 返回一个TreeMap
   */
  public static TreeMap<String, String> bean2TreeMap(Object bean) {
    TreeMap<String, String> requestMap = new TreeMap<String, String>();
    Class<?> cls = bean.getClass();
    Field[] fields = cls.getDeclaredFields();
    try {
      for (int i = 0; i < fields.length; i++) {
        String key = fields[i].getName();
        fields[i].setAccessible(true);
        Object value = fields[i].get(bean);
        if ("sign".equals(key) || value == null || StringUtils.isEmpty(value.toString())) {
          continue;
        }
        requestMap.put(key, value.toString());
      }
    } catch (IllegalAccessException e) {
      e.printStackTrace();
    }
    return requestMap;
  }

  /**
   * 将bean按照@XStreamAlias标识的字符串内容生成以之为key的map对象
   *
   * @param bean
   *          包含@XStreamAlias的xml bean对象
   * @return map对象
   */
  public static Map<String, String> xmlBean2Map(Object bean) {
    Map<String, String> result = Maps.newHashMap();
    List<Field> fields = new ArrayList<Field>(Arrays.asList(bean.getClass().getDeclaredFields()));
    fields.addAll(Arrays.asList(bean.getClass().getSuperclass().getDeclaredFields()));
    for (Field field : fields) {
      try {
        boolean isAccessible = field.isAccessible();
        field.setAccessible(true);
        if (field.get(bean) == null) {
          field.setAccessible(isAccessible);
          continue;
        }

        if (field.isAnnotationPresent(XStreamAlias.class)) {
          result.put(field.getAnnotation(XStreamAlias.class).value(), field.get(bean).toString());
        }

        field.setAccessible(isAccessible);
      } catch (SecurityException e) {
        e.printStackTrace();
      }catch(IllegalArgumentException e){
        e.printStackTrace();
      }catch (IllegalAccessException e) {
        e.printStackTrace();
      }

    }
    return result;
  }

  /**
   * 微信公众号支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php
   * ?chapter=4_3)
   *
   * @param xmlBean
   *          Bean需要标记有XML注解
   * @param signKey
   *          签名Key
   * @return 签名字符串
   */
  public static String createSign(Object xmlBean, String signKey) {
    return createSign(xmlBean2Map(xmlBean), signKey);
  }

  /**
   * 微信公众号支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php
   * ?chapter=4_3)
   *
   * @param params
   *          参数信息
   * @param signKey
   *          签名Key
   * @return 签名字符串
   */
  public static String createSign(Map<String, String> params, String signKey) {

    SortedMap<String, String> sortedMap = new TreeMap<String, String>(params);

    StringBuilder toSign = new StringBuilder();
    for (String key : sortedMap.keySet()) {
      String value = params.get(key);
      if (StringUtils.isNotEmpty(value) && !"sign".equals(key) && !"key".equals(key)) {
        toSign.append(key).append("=").append(value).append("&");
      }
    }

    toSign.append("key=").append(signKey);
    return DigestUtils.md5Hex(toSign.toString()).toUpperCase();
  }

}
